import json
from decimal import Decimal
from django.db import transaction
from meiduo_mall.settings.dev import logger
from utils.response_code import RETCODE
from datetime import datetime
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponseForbidden
from django.http import JsonResponse
from django.shortcuts import render
from django.views import View
from django_redis import get_redis_connection
from apps.goods.models import SKU
from apps.orders.models import OrderInfo, OrderGoods
from apps.users.models import Address
# Create your views here.
'''1.结算订单'''
class OrderSettlementView(LoginRequiredMixin, View):
    def get(self, request):
        user = request.user
        #4.context
        # 1.判断是否存在收货地址
        try:
            addresses = Address.objects.filter(user=user, is_deleted=False)
        # 如果地址为空，渲染模板时会判断，并跳转到地址编辑页面
        except Address.DoesNotExist:
            addresses = None
        # 2.redis查询选中的商品
        redis_client = get_redis_connection('carts')
        redis_data = redis_client.hgetall(user.id)
        carts_dict = {}
        for data in redis_data.items():
            sku_id = int(data[0].decode())
            sku_dict = json.loads(data[1].decode())
            if sku_dict['selected']:
                carts_dict[sku_id] = sku_dict
        total_count = 0
        total_amount = Decimal(0.00)
        freight = Decimal(10.00)
        # 3.再去SKU查商品
        sku_ids = carts_dict.keys()
        skus = SKU.objects.filter(id__in=sku_ids)
        for sku in skus:
            #动态添加两个属性count和amount
            sku.count = carts_dict[sku.id].get('count')
            sku.amount = sku.price * sku.count
            #计算总个数,总金额
            total_count += sku.count
            total_amount += sku.amount
        # 渲染界面
        context = {
            'addresses': addresses,
            'skus': skus,
            'total_count': total_count,
            'total_amount': total_amount,
            'freight': freight,
            'payment_amount':total_amount + freight
        }
        return render(request, 'place_order.html', context)
'''2.提交订单'''
class OrderCommitView(LoginRequiredMixin, View):
    def post(self, request):
        #1.接收参数 json
        user = request.user
        json_dict = json.loads(request.body.decode())
        address_id = json_dict.get('address_id')
        pay_method = json_dict.get('pay_method')
        #2.校验参数,判空,地址,支付方式
        try:
            address = Address.objects.get(id=address_id)
        except Exception as e:
            return HttpResponseForbidden('参数address_id错误')
        if pay_method not in [OrderInfo.PAY_METHODS_ENUM['CASH'],OrderInfo.PAY_METHODS_ENUM['ALIPAY']]:
            return HttpResponseForbidden('参数pay_method错误')
        #3.生成基本订单信息,8个字段;根据年月日十分秒+user.id 9位
        order_id = datetime.now().strftime('%Y%m%d%H%M%S') + ('%09d' %user.id)
        with transaction.atomic():
            #显式的开启一个事务
            save_id = transaction.savepoint()
            #暴力回滚
            try:
                order = OrderInfo.objects.create(
                    order_id=order_id,
                    user=user,
                    address=address,
                    total_count=0,
                    total_amount=Decimal('0'),
                    freight=Decimal('10.00'),
                    pay_method=pay_method,
                    status=OrderInfo.ORDER_STATUS_ENUM['UNPAID'] if pay_method == OrderInfo.PAY_METHODS_ENUM['ALIPAY'] else
                    OrderInfo.ORDER_STATUS_ENUM['UNSEND']
                )
                #4.从redis购物车取出选中的商品
                redis_client = get_redis_connection('carts')
                redis_data = redis_client.hgetall(user.id)
                carts_dict = {}
                for data in redis_data.items():
                    sku_id = int(data[0].decode())
                    sku_dict = json.loads(data[1].decode())
                    if sku_dict['selected']:
                        carts_dict[sku_id] = sku_dict
                #5.遍历商品:
                sku_ids = carts_dict.keys()
                for sku_id in sku_ids:
                    while True:
                        sku = SKU.objects.get(id=sku_id)
                        #读取原始库存
                        origin_stock = sku.stock
                        origin_sales = sku.sales
                        #5.1.判断库存是否充足
                        sku_count = carts_dict[sku_id].get('count')
                        if sku_count > sku.stock:
                            #出错就事物回滚
                            transaction.savepoint_rollback(save_id)
                            return JsonResponse({'code': RETCODE.STOCKERR, 'errmsg': '库存不足'})
                        # #5.2.sku减少库存,增加销量
                        # sku.stock -= sku_count
                        # sku.sales += sku_count
                        # sku.save()
                        # #测试:模拟延时
                        # import time
                        # time.sleep(5)
                        # 5.2.乐观锁更新库存和销量
                        new_stock = origin_stock - sku_count
                        new_sales = origin_sales + sku_count
                        result = SKU.objects.filter(id=sku_id, stock=origin_stock).update(stock=new_stock, sales=new_sales)
                        if result == 0:
                            continue
                        #5.3.spu增加销量
                        sku.spu.sales += sku_count
                        sku.spu.save()
                        #5.4.生成订单商品表, 4个字段
                        OrderGoods.objects.create(
                            order=order,
                            sku=sku,
                            count=sku_count,
                            price=sku.price,
                        )
                        #5.5.计算总价格,总数量
                        order.total_count += sku_count
                        order.total_amount += (sku_count * sku.price)
                        #下单成功或者失败就跳出循环
                        break
                #6.总金额添加运费
                order.total_amount += order.freight
                order.save()
            except Exception as e:
                logger.error(e)
                transaction.savepoint_rollback(save_id)
                return JsonResponse({'code':RETCODE.DBERR, 'errmsg':'下单失败'})
            transaction.savepoint_commit(save_id)
        #7.删除购物车的数据
        p1 = redis_client.pipeline()
        p1.hdel(user.id, *carts_dict)
        p1.srem(user.id, *carts_dict)
        p1.execute()
        return JsonResponse({'code': RETCODE.OK, 'errmsg': '下单成功', 'order_id': order.order_id})
'''3.订单成功'''
class OrderSuccessView(LoginRequiredMixin, View):
    def get(self, request):
        order_id = request.GET.get('order_id')
        payment_amount = request.GET.get('payment_amount')
        pay_method = request.GET.get('pay_method')
        context = {
            'order_id': order_id,
            'payment_amount': payment_amount,
            'pay_method': pay_method
        }
        return render(request, 'order_success.html', context)